%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct id{
	int indice;
	int proxApontador;
	int apontadorFuncao;
	int tipo;
	int linha;
	char nome[40];
	char scope[40];
	char *func; 
	struct id *prox;
};
typedef struct id id;

int insere_id(char *a, int tipo, int linha);
id* cria_id(id* novo);
void imprime_id(void);
int pesquisaVariavel(char *a);

id *tab;
char a[40];
char escopo[40];
int auxIndice;
int tipos;
int achou_tipo;
int achou_variavel;
int charFunc;
int line;
int tam;
int lastFunction;
%}

impressao					"%d"|"%f"|"%s"|"%ld"
abre_parenteses			"("
fecha_parenteses			")"
ponteiro					["*"|"**"]
delim					[ \t]
newline					\n
espaco					{delim}+
digito					[0-9]
numero					{digito}+\.{digito}+
se						if
senao					else
enqunato					while
faca						do
repita					for
fim						";"
tipo						"int"|"float"|"char"|"double"|"struct"
letra					[a-zA-Z]
variavel					{ponteiro}*{letra}({letra}|{digito}|_{letra}|_{digito})*
funcao					{ponteiro}*{letra}({letra}|{digito}|_{letra}|_{digito})*{abre_parenteses}
igual					"="
operacao					{ponteiro}|"+"|"-"|"/"
escopoStruct				"};"
fimFuncao					"}"

/* int == 1; double == 2; char == 3; float == 4; apontador == 5; void == 6; struct == 7; funcao == 8*/
%%

{newline}      { ++line; }
{operacao}       { /* faz nada */ }
{espaco}       { /* faz nada */ }
{numero}       { /* faz nada */}
{se}           { /* faz nada */}
{senao}        { /* faz nada */}
enqunato		{ /* faz nada */}
faca			{ /* faz nada */}
repita		{ /* faz nada */}
{igual}        { /* faz nada */}
{impressao}    { /*faz nada */}
{tipo}         {
		      	achou_tipo = 1;
                   	tipos = tipo_id(strdup(yytext));
				if(tipos == 7)
					charFunc = 2;
				else if(tipos == 0)
					achou_tipo=0;
			}

{variavel}      {       
			  	strcpy(a,strdup(yytext));
					if(tipos !=7)
	               		charFunc=0;
					else
						strcpy(escopo,"global");				
					achou_variavel = 1;
					return 1;
			 }

{funcao}        {               
				strcpy(a,strdup(yytext));
                    tam=strlen(a);
                    a[tam-1]='\0';
                    printf("%s\n",a);
				charFunc=1;
				strcpy(escopo, a);

				if(strcmp(escopo,"main")!=0)
					strcpy(escopo,"global");
				lastFunction = 0;

				if(strcmp(a,"main")==0&& achou_tipo==0){
					achou_tipo=1;
					tipos=6;
				}
                    return 1;
               }

{escopoStruct}	{
				tipos = 7;
				lastFunction = 1;
				strcpy(escopo,"");						
			}

{fimFuncao}	{
				strcpy(escopo,"");
				lastFunction = 1;
			}

{fim}          {
               	achou_tipo=0;
							
               }

.              { /* faz nada */}
%%

int main(void){
	charFunc=0;
	achou_tipo=0;
	auxIndice = 1;
	strcpy(escopo,"global");
	int i;

     while(yylex()){
     	if(achou_tipo==1 && (pesquisaVariavel(a) == 1)){
			if(a[0] =='*' && charFunc == 0){
				insere_id(a,5,line);
				tam=strlen(a);
				for(i=0;i<tam-1;i++){
					a[i] = a[i+1];
				}
				a[tam-1] = '\0';

				if(a[0]=='*'&& (pesquisaVariavel(a) == 1)){
					insere_id(a,5,line);								
					tam=strlen(a);
					for(i=0;i<tam-1;i++){
						a[i] = a[i+1];
					}
					a[tam-1] = '\0';
				}
				if(pesquisaVariavel(a) == 1)
					insere_id(a,tipos,line);
			}

			else if(charFunc == 0){ 
				insere_id(a, tipos, line);
			}

			else{
				insere_id(a, tipos, line);
			}
		}
	 }
      imprime_id();
      return 0;
}

int yywrap() {
        return 1;
}

id* cria_id(id* novo){
	novo = (id *)malloc(sizeof(id));
	novo->tipo = 0;
	novo->prox = NULL;
	novo->linha = 0;
	novo->indice = auxIndice++;
	novo->proxApontador = 0;
	return novo;
}

int insere_id(char a[40], int tipo, int line){
    id *novo = cria_id(novo);
    strcpy(novo->nome,a);
    strcpy(novo->scope,escopo);
    novo->tipo=tipo;
    novo->linha = line+1;
    if(tipo == 5){
	  novo->func = "apontador";
	  novo->proxApontador = auxIndice;
    }else
    if(charFunc==0){
    	novo->func = "variavel";
   } 
   else if(charFunc==2){
	novo->func = "registro";
   }
    else{
    	novo->func = "funcao";
    }
    if(tab == NULL){
	tab = novo;
	return 1;
    }else{
    		id *inicio;
		inicio = tab;
	while(inicio->prox != NULL){
		inicio = inicio->prox;
	}
    	if((novo->nome != NULL) || (novo->tipo != 0) || (novo->prox != NULL) || strcmp(novo->scope,escopo) != 0){
		inicio->prox=novo;
   		return 1;
	}
   }
	
	return 0;
}

int pesquisaVariavel(char *temp){
	int sai = 0;
	id *aux = tab;

	while( (sai == 0) && (aux != NULL)){
		if(strcmp(temp,aux->nome) == 0 && charFunc !=1 && strcmp(escopo,aux->scope)==0){
			//printf("Variável %s declarada na linha %d\n", temp, aux->linha); 
			sai = 1;
		}
		aux = aux->prox;
	}
	if(sai == 0){
		//printf("Variável não declarada\n");
		return 1;
	}
	if(sai == 1)
		return 0;
}

void imprime_id(void) {
	printf("indice\ttipo\tregistro\tnome\t\tescopo\tlinha\tapontandor\n");
        for (; tab != NULL; tab = tab->prox){
                printf("%d \t%d \t  %s\t%s\t\t%s\t%d\t%d\n",tab->indice,tab->tipo, tab->func, tab->nome, tab->scope, tab->linha, tab->proxApontador);
        }
}

int tipo_id(char *id){
	if(strcmp(id,"int") == 0)
		return 1;
	else if(strcmp(id,"double") == 0)
		return 2;
	else if(strcmp(id,"char")  == 0)
		return 3;
	else if(strcmp(strdup(yytext),"float") == 0)
		return 4;
	else if(strcmp(strdup(yytext),"struct") == 0)
		return 7;
	else
		return 0;
}

